﻿using System;
using System.Collections.Generic;
using System.Text;
using Walson.Scientific;

namespace Scientific.Communication
{
    /// <summary>
    /// WCDMA
    /// </summary>
    static public class Wcdma
    {
        /// <summary>
        /// 产生指定长度的 OVSF 码，并给出码表中指定编号的码序列
        /// </summary>
        /// <param name="codeLength">码长度</param>
        /// <param name="codeIndex">码编号</param>
        /// <returns>OVSF 码</returns>
        static public sbyte[] OvsfGenerator(int codeLength,int codeIndex)
        {
            sbyte[] result = new sbyte[codeLength];
            result[0] = 1;
            
            Stack<int> path = new Stack<int>();
            codeLength = (int)Math.Log(codeLength, 2);
            // 计算指定位置的码在码树中的位置，形成一条由根寻找码字的路径
            while (codeLength != 0)
            {
                path.Push(codeIndex % 2);
                codeIndex /= 2;
                codeLength --;
            }

            // 按照路径生成指定的码序列
            codeLength = 1;
            while (path.Count != 0)
            {
                if (path.Pop() == 0)
                {
                    for (int i = 0; i < codeLength; i++)
                    {
                        result[codeLength + i] = result[i];
                    }
                }
                else
                {
                    for (int i = 0; i < codeLength; i++)
                    {
                        result[codeLength + i] = (sbyte)(0 - result[i]);
                    }
                }
                codeLength += codeLength;
            }

            return result;
        }

        /// <summary>
        /// 扩频
        /// </summary>
        /// <param name="bits">原始比特流</param>
        /// <param name="ovsf">OVSF 码编号</param>
        /// <returns>扩频后的码片</returns>
        static public sbyte[] DDS(byte[] bits,sbyte[] ovsf)
        {
            sbyte[] dss = new sbyte[bits.Length * ovsf.Length];

            sbyte[] reversedOvsf = new sbyte[ovsf.Length];
            for (int i = 0; i < ovsf.Length; i++)
            {
                reversedOvsf[i] = (sbyte)(0 - ovsf[i]);
            }

            for (int i = 0; i < bits.Length; i++)
            {
                if (bits[i] == 1)
                    Array.Copy(ovsf, 0, dss, i * ovsf.Length, ovsf.Length);
                else
                    Array.Copy(reversedOvsf, 0, dss, i * reversedOvsf.Length, reversedOvsf.Length);
            }

            return dss;

        }
    }

    /// <summary>
    /// 调制
    /// </summary>
    static public class Modulation
    {
        /// <summary>
        /// QPSK 调制
        /// </summary>
        /// <param name="bits">码片</param>
        /// <param name="sampRate">采样倍数</param>
        /// <returns>QPSK 信号</returns>
        static public double[] QPSK(sbyte[] bits,int sampRate)
        {
            List<double> result = new List<double>();

            // s(t)=I(t)cos(wt) + Q(t)sin(wt)
            // 四种载波
            // I,0
            double[] temp1 = Signals.Cos(sampRate, 0).ToArray();
            // I,1
            double[] temp2 = Signals.Cos(sampRate, Math.PI).ToArray();
            // Q,0
            double[] temp3 = Signals.Cos(sampRate, Math.PI / 2.0).ToArray();
            // Q,1
            double[] temp4 = Signals.Cos(sampRate, Math.PI * 3.0 / 2.0).ToArray();
            //double[,] carrier = new double[4, temp1.Length];
            List<double>[] carrier = new List<double>[4];

            for (int i = 0; i < 4;i++ )
            {
                carrier[i] = new List<double>(temp1);
            }

            for (int i = 0; i < temp1.Length;i++ )
            {
                // I(t)=0, Q(t)=0
                carrier[0][i] = temp1[i] + temp3[i];
                // I(t)=0, Q(t)=1
                carrier[1][i] = temp1[i] + temp4[i];
                // I(t)=1, Q(t)=0
                carrier[2][i] = temp2[i] + temp3[i];
                // I(t)=1, Q(t)=1
                carrier[3][i] = temp2[i] + temp4[i];
            }

            // 理论上讲，需要将信号分为 I、Q 两路，再对两路分别进行 BPSK 调制。由于上面已经产生了四种波形，并且分别对应了四种码字，因此这里直接进行调制。

            for (int i = 0; i < bits.Length; i += 2)
            {
                if ((bits[i] == 0 && bits[i + 1] == 0) || (bits[i] == -1 && bits[i + 1] == -1))
                {
                    result.AddRange(carrier[0]);
                }
                else if ((bits[i] == 0 || bits[i] == -1) && bits[i + 1] == 1)
                {
                    result.AddRange(carrier[1]);
                }
                else if (bits[i] == 1 && (bits[i + 1] == 0 || bits[i + 1] == -1))
                {
                    result.AddRange(carrier[2]);
                }
                else if (bits[i] == 1 && bits[i + 1] == 1)
                {
                    result.AddRange(carrier[3]);
                }
            }

            return result.ToArray();
        }
    }

    /// <summary>
    /// 解调
    /// </summary>
    static public class Demodulation
    {

    }
    
}
